﻿/*
Copyright (c) 2010 Vratislav Cermak (vratacermak@gmail.com)
 
This file is part of TeachMe Project. See http://code.google.com/p/teach-me for more information.
 
TeachMe is an open source project. Using of TeachMe is free of charge.
It is distributed under GNU General Public License version 3 (GPLv3).
GPLv3 can be found at http://www.gnu.org/licenses/gpl.html.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TeachMe.Application.Data;
using TeachMe.Application.Events;
using TeachMe.Application.Exceptions;
using TeachMe.Application.Forms;
using TeachMe.Application.Properties;

namespace TeachMe.Application
{
    public class OnlineDictsManager
    {
        private readonly Root _root;
        private readonly PseudoModalForm _parentForm;
        private readonly FolderBrowserDialog _dlgThemesFolder;
        private readonly SaveFileDialog _dlgSaveOnlineDict;

        public event EventHandler<InputOutputEventArgs<string, bool>> IsDictionaryLoaded;
        public event EventHandler<InputOutputEventArgs<string, Dictionary>> GetLoadedDictionary;
        public event EventHandler<InputOutputEventArgs<string, Guid>> GetLoadedDictionaryId;
        public event EventHandler<InputEventArgs<Dictionary>> RefreshDictionaryUI;
        public event EventHandler<InputEventArgs<Dictionary>> AddDictionaryUI;

        public OnlineDictsManager(Root root, PseudoModalForm parentForm)
        {
            _root = root;
            _parentForm = parentForm;
            
            _dlgThemesFolder = new FolderBrowserDialog {Description = Resources.SelectFolderForOnlineDicts };
            _dlgSaveOnlineDict = new SaveFileDialog { Filter = Resources.DictionaryFilesFilter, Title = Resources.SaveOnlineDict };
        }

        private void AddOnlineDictionaries(WebContentDownloader<String, OnlineDictsForm.OnlineDicts.Item>.Job[] jobs)
        {
            // TODO: add logging

            if (jobs.Length > 0)
            {
                if (Directory.Exists(_root.UserSettings.ThemesDirectory))
                {
                    _dlgThemesFolder.SelectedPath = _root.MachineSettings.LastBrowseDirectory;
                }

                if (_dlgThemesFolder.ShowDialog() == DialogResult.OK)
                {
                    _root.MachineSettings.LastBrowseDirectory = _dlgThemesFolder.SelectedPath;

                    string directory = _dlgThemesFolder.SelectedPath;

                    foreach (var job in jobs)
                    {
                        Guid dictId;
                        bool overwriting = false;
                        string path = Path.Combine(directory, Path.GetFileName(job.Context.Path));

                        while (true)
                        {
                            // are we overwriting file?
                            if (File.Exists(path))
                            {
                                if (MessageBox.Show(String.Format(Resources.FileExists, path), Resources.MessageBoxCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
                                {
                                    // user dows not want to overwrite, let him change file name

                                    _dlgSaveOnlineDict.FileName = path;

                                    if (_dlgSaveOnlineDict.ShowDialog(_parentForm) == DialogResult.OK)
                                    {
                                        path = _dlgSaveOnlineDict.FileName;

                                        // new file name selected, test once again if it exists
                                        continue;
                                    }

                                    // user pressed cancel
                                    return;
                                }
                            }

                            // are we overwriting existing (loaded) dictionary?
                            if (InputOutputEventArgs<string, bool>.Fire(this, IsDictionaryLoaded, path))
                            {
                                if (MessageBox.Show(String.Format(Resources.OverwriteUsedDictionary, path), Resources.MessageBoxCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
                                {
                                    // user does not want to overwrite loaded dictionary, let him choose file name once again
                                    // TODO: overwrite dialog is displayed twice
                                    continue;
                                }

                                // we will use ID of old dict and overwrite content
                                dictId = InputOutputEventArgs<string, Guid>.Fire(this, GetLoadedDictionaryId, path);
                                overwriting = true;
                            }
                            else
                            {
                                // just create new id
                                dictId = Guid.NewGuid();
                            }

                            break;
                        }

                        using (StreamWriter writer = new StreamWriter(path, false, Encoding.UTF8))
                        {
                            writer.Write(job.Result);
                        }

                        Dictionary.UpdateId(path, dictId);

                        if (overwriting)
                        {
                            Dictionary dictionary = InputOutputEventArgs<string, Dictionary>.Fire(this, GetLoadedDictionary, path);

                            _root.RefreshDictionary(dictionary);

                            InputEventArgs<Dictionary>.Fire(this, RefreshDictionaryUI, dictionary);
                        }
                        else
                        {
                            if (!AddExistingDictionary(path))
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }

        private bool AddExistingDictionary(string path)
        {
            // TODO: refactor usage of similar blocks and use this method instead

            Dictionary dictionary;

            try
            {
                dictionary = _root.AddNewDictionary(path);
            }
            catch (DictionaryException exception)
            {
                Logging.Error(GetType(), exception, "Dictionary could not be added.");

                MessageBox.Show(Resources.DictionaryCreateError, Resources.MessageBoxCaption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            if (dictionary != null)
            {
                InputEventArgs<Dictionary>.Fire(this, AddDictionaryUI, dictionary);
            }

            return true;
        }

        public void AddOnlineDicts()
        {
            OnlineDictsForm form = new OnlineDictsForm(_root);
            _root.FormsManager.Add(form);

            form.PseudoParent = _parentForm;
            form.Show();

            form.Closed += delegate
            {
                try
                {
                    if (form.DialogResult == DialogResult.OK)
                    {
                        List<WebContentDownloader<String, OnlineDictsForm.OnlineDicts.Item>.Job> jobs = new List<WebContentDownloader<string, OnlineDictsForm.OnlineDicts.Item>.Job>();

                        foreach (OnlineDictsForm.OnlineDicts.Item item in form.Result)
                        {
                            WebContentDownloader<String, OnlineDictsForm.OnlineDicts.Item>.Job job = new WebContentDownloader<string, OnlineDictsForm.OnlineDicts.Item>.Job();
                            job.Context = item;
                            job.Link = String.Format("http://www.teachme.cz/get_dict.php?id={0}", item.Id);

                            jobs.Add(job);
                        }

                        WebContentDownloader<String, OnlineDictsForm.OnlineDicts.Item>.Download(_root, _parentForm, jobs.ToArray(), Resources.DownloadingDictionaries, AddOnlineDictionaries);
                    }
                }
                finally
                {
                    _root.FormsManager.Remove(form);
                }
            };
        }
    }
}
